package com.why.rpc.core.server.starter;


import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import com.why.rpc.core.common.codec.CommonDecoder;
import com.why.rpc.core.common.codec.CommonEncoder;
import com.why.rpc.core.common.nacos.ServiceRegistry;
import com.why.rpc.core.common.serializable.CommonSerializable;
import com.why.rpc.core.common.serializable.KroSerializer;
import com.why.rpc.core.server.config.WhyRpcConfigPorperties;
import com.why.rpc.core.server.handler.NettyServerHandler;
import com.why.rpc.core.server.hook.ServerLogOut;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

/**
 * @program: why-rpc-framework
 * @description: 完成注册中心的启动
 * @author: @why
 * @create: 2021-03-15 16:00
 **/

public class NettyRpcServer implements Server {
    private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(NettyRpcServer.class);
    private int port;
    private String host;
    private ServiceRegistry registry;
    private CommonSerializable serializable;

    public NettyRpcServer() {
    }

    //完成注册中心的启动
    {
        serializable = new KroSerializer();
        port = WhyRpcConfigPorperties.getPort();
        host = WhyRpcConfigPorperties.getHost();
    }

    @Override
    public void start() {
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();
        try {
            log.info("初始化rpc服务端...");
            ServerBootstrap bootstrap = new ServerBootstrap();
            //指定老板和员工
            bootstrap
                    .group(boss, worker)
                    .channel(NioServerSocketChannel.class)
                    //选项介绍见博客分类的netty部分
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childOption(ChannelOption.TCP_NODELAY, true)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    //老板接到活后，把任务分给员工，此时员工应该做的事情,进行解码编码和调用handler对请求处理
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            //在管道上注册处理程序·
                            ChannelPipeline pipeline = ch.pipeline();
                            //30秒没收到读请求  发送一个包，30秒内NettyServerHandler#ChannelRead()没有呗调用 发送一个包
                            pipeline.addLast(new IdleStateHandler(30, 0, 0, TimeUnit.SECONDS));
                            pipeline.addLast(new CommonDecoder());
                            pipeline.addLast(new CommonEncoder(serializable));
                            pipeline.addLast(new NettyServerHandler());

                        }
                    });
            //同步绑定端口号。
            log.info("初始化完成");
            log.info("开始绑定端口号。。。");
            ChannelFuture future = bootstrap.bind(port).sync();
            log.info("绑定端口号成功。。。");
            log.info("开始向jvm注册钩子。。。");
            ServerLogOut.logOut().clearAllService();
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            log.error("RpcServer发生未知异常。。", e);
        } finally {

            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }


    }

}